#ifndef RTE_KB1281_DGUSII_H
#define RTE_KB1281_DGUSII_H

#include <kSerial.h>
#include <logger_rte.h>
#include "dgus.h"

class dgusii {
public:
    int begin(kSerial *serl, uint8_t power_pin) {
        serial = serl;
        serial->begin(115200);
        pinMode(power_pin, OUTPUT);
        digitalWrite(power_pin, HIGH);
        pwrPin = power_pin;
        poweron = true;
        lock = rtos::Create_Mutex();
        dgus_init(ser_available_handler_cb, ser_recv_handler_cb, ser_send_handler_cb, packet_handler_cb);
        return 0;
    }

    static void beep(uint8_t b) {
        rtos::mutex_lock(lock);
        if (poweron) {
            state = dgus_play_sound(1, 1, 64, b ? 2 : 0);
        }
        rtos::mutex_unlock(lock);
    }

    static void set_var_str(uint16_t index, uint8_t *var) {
        // logger.debug("set_var_str 0x%x %s", index, var);
        int len = strlen((const char *) var);
        if (len > 20)len = 20;
        rtos::mutex_lock(lock);
        if (poweron)
            state = dgus_set_var8(index, var, len);
        rtos::mutex_unlock(lock);
        if (state != 0) {
            logger.error("set_var_str 0x%x %d", index, state);
        }
    }

    static void set_page(uint8_t page) {
        logger.debug("set_page %d", page);
        uint8_t pg = 0;
        if (poweron) {
            do {
                rtos::mutex_lock(lock);
                state = dgus_set_page(page);
                rtos::mutex_unlock(lock);
                if (state != 0) {
                    logger.error("set_page %d failed", state);
                }
                rtos::mutex_lock(lock);
                DGUS_RETURN r = dgus_get_var(PicPage, &pg, 1);
                rtos::mutex_unlock(lock);
            } while (page != pg);
        }
    }

    static void set_var(uint16_t addr, uint32_t data) {
        // logger.debug("set_var_str %d", addr);
        if (poweron) {
            do {
                rtos::mutex_lock(lock);
                state = dgus_set_var(addr, data);
                rtos::mutex_unlock(lock);
                if (state) {
                    logger.debug("set_var_str 0x%x = %d %d", addr, data, state);
                }
            } while (state != 0);
        }
    }

    // static void set_pvar(uint16_t addr, uint8_t *data, uint8_t size) {
    //     // logger.debug("set_var_str %d", addr);
    //     dgus_set_var8(addr, data, size);
    // }

    static void get_var(uint16_t adr, uint8_t *data, uint8_t size) {
        if (!poweron)return;
        do {
            rtos::mutex_lock(lock);
            state = dgus_get_var(adr, data, size);
            rtos::mutex_unlock(lock);
            if (state) {
                logger.debug("get_var 0x%x size=%d %d", adr, size, state);
            }
        } while (state != 0);
    }

    static uint8_t get_page() {
        uint16_t p;
        p = 255;
        do {
            rtos::mutex_lock(lock);
            if (poweron)
                state = dgus_get_page(&p);
            rtos::mutex_unlock(lock);
            if (state) {
                logger.debug("get_page %d", state);
            }
        } while (state != 0);
        return p;
    }

    static void set_brightness(uint8_t val) {
        if (!poweron)return;
        do {
            rtos::mutex_lock(lock);
            state = dgus_set_brightness(val);
            rtos::mutex_unlock(lock);
            if (state) {
                logger.debug("set_brightness %d", state);
            }
        } while (state != 0);
        logger.debug("set_brightness %d", val);
    }

    static uint8_t ser_available_handler_cb();

    static char ser_recv_handler_cb();

    static void ser_send_handler_cb(const char *data, size_t len);

    static void packet_handler_cb(char *data, uint8_t cmd, uint8_t len, uint16_t addr, uint8_t bytelen);

    static kSerial *serial;
    static bool poweron;
    static uint8_t pwrPin;

    static void shutdown(bool b);

    static uint8_t state;
    static void *lock;
};

#endif // RTE_KB1281_DGUSII_H
